/*! \file fat.c
 *   \brief Contiene todos los algoritmos de acceso a FAT
 *   \TODO hacer los algoritmos...
 *
 *	Contiene las estructuras y funciones necesarias para acceso a la FAT
 */

#include "fs/fat.h"
#include <kernel/libk/libk.h>
#include <kernel/libk/string.h>
#include <kernel/mem/mem_part_kernel.h>
#include <kernel/definiciones.h>
#include <kernel/syscall.h> //para codigos de error.
#include <kernel/system.h>
#include <shell/teclado.h>
#include <shell/shell.h>
#include <shell/sys_video.h>
#include <kernel/drivers/floppy.h>
#include <video.h>


/**
 * @brief Inicializa el ruta por defecto /
 */
void vFnInicializarPath()
{
	int iN ;
	for (iN = 0 ; iN  < 254 ; iN++)
	{
		stuPATHCD[0].stPATH[iN]= ' ';
	}
	iFnCopiaCadena(stuPATHCD[0].stPATH,"/");
}

/**
 * @brief Recibe un nombre en formato FAT ( KERNEL  BIN ) y lo transforma a
	     un formato tipo string: KERNEL.BIN\0
 * @param puNombreFat Nombre del archivo original
 * @param puNombreAdaptado Nombre adaptado
 */
void vFnAdaptarNombre (char *puNombreFat, char *puNombreAdaptado)
{
	int  iX=0,iZ;
	iFnCopiaCadena(puNombreAdaptado,"            ");
	for( iZ=0  ; iZ<11 ;  iZ++)
	{
		if ( (iZ==8) && (puNombreFat[8]!=' ') )
		{
			puNombreAdaptado[iX]='.';
			iX++;
		}
		puNombreAdaptado[iX]  = puNombreFat[iZ];
		if (puNombreFat[iZ] != ' ')
		iX++;
	}
	puNombreAdaptado[iX]='\0';
}


/**
 * @brief Devuelve el tama�o del directorio del root
 * @returns el tama�o del directorio del root
 * @date 04/08/2008
 */
uint16_t t16FnObtenerTamanioRootDir()
{
	// 14 = 224*32/512
	return ((pstuFsFatHandleHandle->header->root_entries * sizeof(stuFsDirectorioFAT)) / SECTOR_SIZE);
}

/**
 * @brief Devuelve el cluster de inicio del Directorio root
 * @returns cluster de inicio del Directorio root
 * @date 04/08/2008
 */
uint16_t  t16FnObtenerComienzoRootDir()
{
	// (1+0+(2*9))
	return ( 1 + pstuFsFatHandleHandle->header->hidden_sectors + (pstuFsFatHandleHandle->header->fats * pstuFsFatHandleHandle->header->sectors_per_fat));
}



/**
 * @brief Busca un nombre de archivo en la fat
 * @param PID del proceso
 * @returns Posici�n en el vector de procesos o -1 si no existe
 * @date 04/08/2008
 */
int iFnBuscarArchivoFat (char *pcNombre, stuFsDirectorioFAT *pstFsFatDirentDatosArchivo , stuFsHandleFat *pstuFsFatHandleHandle)
{

	char stNombreAux[MAX_PATH_LEN];    //String auxiliar donde se va parseando el nombre por tramos (entre "/")
	char stNombreArchivos[MAX_PATH_LEN];    //String en el que se guarda cada nombre levantado del disco
	char stNombreMay[MAX_PATH_LEN];
	//uint8_t uX;
	int iJ ;
	int iDirLen;    //nombre actual es un archivo o directorio (ver funcion str_dir_len). Si es archivo iDirLen=-1
					//si es directorio, iDirLen=cantidad de caracteres del nombre
	uint8_t uRootDirFlag=1;   //Directorio en el que se busca es el Root.
	//Sector de comienzo y cantidad de sectores del directorio a leer
	dword dwDirSector, dwTamanioDir;


	iFnCopiaCadena(stNombreMay, pcNombre) ;
	//Pasar el nombre a buscar a mayusculas (recordar que la FAT solo usa mayusculas)
	vFnStrUpr(stNombreMay);


	//El primer directorio a leer sera el Root Dir, asi que cargo sus parametros
	dwDirSector = t16FnObtenerComienzoRootDir();	//Sector de comienzo del Directorio raiz
	dwTamanioDir = t16FnObtenerTamanioRootDir();	//Cantidad de sectores asignados al root


	stuFsDirectorioFAT *pstuFsFatDirentAuxFat;     //Estructura para levantar los datos de cada archivo de disco

	do
	{

		iFnBuscarArchivo_break:

			if ((iDirLen=iFnLongitudCadena(stNombreMay)) > 0)		//devuelve -1 si le paso como parametro un archivo
			{											//Si es un directorio, buscarlo y apuntar
				//vFnCopiaCadena3(stNombreAux, pcNombre, iDirLen);	//nombre al proximo directorio/archivo
				iFnCopiaCadena(stNombreAux,pstFnCadenaIzquierda(pcNombre,iDirLen));
				pcNombre = pcNombre + iDirLen + 1;
			}
			else
			{
				if(iFnCopiaCadena(stNombreAux, stNombreMay) <= 0)            //Si llego aca, *nombre es un archivo
				{ vFnImprimir("NO SE COPIO NADA!\n");
					return -1;
				}
			}


		do
		{
			// Leo todo un sector
			leerSector( byBuffer ,dwDirSector);

			pstuFsFatDirentAuxFat = (stuFsDirectorioFAT *) byBuffer;
			//Recorro desde 0-16 (que son las cantidad de entradas de archivos que hay por sector)
			for( iJ=0 ; iJ < (SECTOR_SIZE / sizeof(stuFsDirectorioFAT)) ; iJ++) //for (iJ = 0; iJ < pstuFsFatHandleHandle->header->root_entries ; iJ++)/
			{

				if( (pstuFsFatDirentAuxFat->filename[0]!=' ') &&(pstuFsFatDirentAuxFat->filename[0]!=FAT_EMPTY) && (pstuFsFatDirentAuxFat->filename[0]!=FAT_DELETED) && !(pstuFsFatDirentAuxFat->attributes & 0x0D) /*&& (pstuFsFatDirentAuxFat->attributes & 0x20)*/)
				{
					vFnAdaptarNombre( pstuFsFatDirentAuxFat->filename , stNombreArchivos);
					if ( iFnCompararCadenas( stNombreArchivos, stNombreAux)==1 ) //Devuelve un 1 si la cadena1 es igual a la cadena2
					{
						if (iDirLen < 0) // es < 0 si le pase un archivo
						{
							ucpFnCopiarMemoria( (unsigned char*) pstFsFatDirentDatosArchivo, (unsigned char*) pstuFsFatDirentAuxFat, sizeof(stuFsDirectorioFAT));
							vFnImprimir("\n**********ARCHIVO!!!!!************************\n");

							return 1;
						}
						dwDirSector = pstuFsFatDirentAuxFat->starting_cluster + 31; // 19 +31 = 50
	//le suma 31 porq tiene q ir a buscar la entrada al area de datos, ya que solo los sectores del root son los que
	//estan contiguos, y en este caso estamos buscando el archivo en otro directorio.
						dwTamanioDir = 0xffff;
						uRootDirFlag=0;    //Ahora voy a buscar en otro directorio
						//FALSE = 0
						goto iFnBuscarArchivo_break;
					}
				}

				pstuFsFatDirentAuxFat++;
			}
			if (uRootDirFlag==1) //TRUE = 1
			{
				dwDirSector++;

				if (dwDirSector > (t16FnObtenerComienzoRootDir() + t16FnObtenerTamanioRootDir() ))
				return 0;
			}
			else
			{

				if ((dwDirSector = pstuFsFatHandleHandle->get_next_cluster( pstuFsFatHandleHandle->fat1, dwDirSector ))==LAST_SECTOR)
				return 0;
			}
		} while (dwDirSector != LAST_SECTOR );



	}
	while ( iDirLen > 0 );

	//Si llegue aqui, archivo no encontrado.
	return 0;
}

/**
 * @brief Muestra informacion de la estructura de directorio pasada como parametro
 * @param pstuFsFatDirentDirEntr Puntero al directorio de comienzo
 * @returns 0
 * @date 04/08/2008
 */
int iFnListarContenidoDir(stuFsDirectorioFAT *pstuFsFatDirentDirEntr)
{
	static int iN=0;
  if (iN==0)
	 vFnImprimir("\n stNombre \tStarting Cluster \tTamanio del Archivo \t fecha");
    if( (pstuFsFatDirentDirEntr->filename[0]!=' ') &&(pstuFsFatDirentDirEntr->filename[0]!=FAT_EMPTY) && (pstuFsFatDirentDirEntr->filename[0]!=FAT_DELETED) && !(pstuFsFatDirentDirEntr->attributes & 0x0D) )
	{
		char stNombre[12];
		
		vFnAdaptarNombre(pstuFsFatDirentDirEntr->filename , stNombre);
		//vFnImprimir("\n stNombre: %s\n Starting Cluster: %d\n Tamanio del Archivo: %d\n fecha: %d/%d/%d %d:%d:%d\n",
			vFnImprimir("\n %s\t\t%d\t\t%d\t\t%d/%d/%d %d:%d:%d",
			stNombre ,
			pstuFsFatDirentDirEntr->starting_cluster,
			pstuFsFatDirentDirEntr->filesize ,
		   	FAT_DIRENT_DATE_YEAR( pstuFsFatDirentDirEntr->create_date ),
		     	FAT_DIRENT_DATE_MONTH( pstuFsFatDirentDirEntr->create_date ),
		     	FAT_DIRENT_DATE_DAY( pstuFsFatDirentDirEntr->create_date ),
		     	FAT_DIRENT_TIME_HOUR( pstuFsFatDirentDirEntr->create_time ),
		     	FAT_DIRENT_TIME_MIN( pstuFsFatDirentDirEntr->create_time ),
		     	FAT_DIRENT_TIME_SEC( pstuFsFatDirentDirEntr->create_time )
			    );

		//SHELL_INTERACTIVO;
     /* if (iN==10)
		{
		  cFnPausa();
		  iN=0;
		}
		else*/ 
		  iN++;
	}
	return 0;
}

/**
 * @brief Esta funcion imprime los nombres de todos los archivos que se hallen en el Root
 * @param pstuFsFatHandleHandle Punto donde comienza el directorio raiz
 * @date 24/10/2008
 */
void vFnListarRootDir(stuFsHandleFat *pstuFsFatHandleHandle)
{
	// Obtengo el sector de inicio del directotio root
	int iSectorOriRoot= 19;//sodium_fat_drv_get_root_dir_sector( pstuFsFatHandleHandle->header );//uint16_t iSectorOriRoot

	int iX, iW,iCantSector;
	//char stNombre[MAX_PATH_LEN];

	stuFsDirectorioFAT *pstuFsFatDirentDatos;

	// Obtengo la cantidad de sectores totales que ocupa el directorio
	iCantSector = 14;//(pstuFsFatHandleHandle->header->root_entries * sizeof(stuFsDirectorioFAT)) / SECTOR_SIZE;

	//Recorre des el inicio del sector del directorio hasta el numero q abarque la cantidad de sectores que ocupa.
	for ( iX=iSectorOriRoot ; iX < (iSectorOriRoot + iCantSector);iX++)
	{
		// Leo todo un sector
		if(leerSector(byBuffer ,iX)!=1)
		{
		  vFnImprimir("Error al leer sector del diskette");
		  return;
		}

		// Acomodo los bytes de acuerdo al formato de la estructura de directorio
		pstuFsFatDirentDatos = (stuFsDirectorioFAT*)byBuffer;
		// itero hasta la cantidad de entradas por sector (es decir hasta la cantidad de entradas que caben en 512)
		for( iW=0 ; iW < 16 ; iW++)
		{
			// Para cada entrada consulto el primer bit
			//Consulto si el primer valor no es cero, sino es borrado, con 0x0D evito listar los ocultos - del sistema - etiquetas
			if ( (pstuFsFatDirentDatos->filename[0]!=FAT_EMPTY)  && !(pstuFsFatDirentDatos->attributes & 0x0D ) && !(pstuFsFatDirentDatos->attributes & 0x02) )
			{
				//sodium_fat_drv_show_dirent( pstuFsFatDirentDatos->filename );
				iFnListarContenidoDir( pstuFsFatDirentDatos );
			}
			pstuFsFatDirentDatos++;
		}
	}
	return;
}

/**
 * @brief Devuelve el cluster de comienzo. Usada para verificar la existencia de directorios en el raiz
 * @param pconcNombre
 * @returns -1 si no se encontro el directorio o el numero de cluster de inicio el directorio
 * @date 04/08/2008
 */
int iFnExisteRaiz (const char *pstNombre , struct stuFsHandleFat *pstuFsFatHandleHandle)
{

	char stNombreAux[MAX_PATH_LEN];    //String auxiliar donde se va parseando el nombre por tramos (entre "/")
	char stNombreArchivos[MAX_PATH_LEN];    //String en el que se guarda cada nombre levantado del disco
	char stNombreMay[MAX_PATH_LEN];
	int iJ ;
	//Sector de comienzo y cantidad de sectores del directorio a leer
	dword dwDirSector, dwTamanioDir;
//si llega aca con una barra al comienzo se la saco  , para buscar correctamente el nombre
	if(pstNombre[0] =='/')
		iFnCopiaCadena(stNombreMay, pstFnCadenaDerecha(pstNombre,iFnLongitudCadena(pstNombre)-1)) ;
	else
	iFnCopiaCadena(stNombreMay, pstNombre) ;
	//Pasar el nombre a buscar a mayusculas (recordar que la FAT solo usa mayusculas)
	vFnStrUpr(stNombreMay);


	//hardcodeo por q las funciones no traian bien los valores
	dwDirSector = 19;	//Sector de comienzo del Directorio raiz
	dwTamanioDir = 14;	//Cantidad de sectores asignados al root


	stuFsDirectorioFAT *pstuFsFatDirentAuxFat;     //Estructura para levantar los datos de cada archivo de disco

		if(iFnCopiaCadena(stNombreAux, stNombreMay) <= 0)            //Si llego aca, *nombre es un archivo
		{ vFnImprimir("NO SE COPIO NADA!\n");
		return -1;
		}

	do
		{
			// Leo todo un sector
			leerSector(byBuffer ,dwDirSector);

			pstuFsFatDirentAuxFat = (stuFsDirectorioFAT *) byBuffer;
			//Recorro desde 0-16 (que son las cantidad de entradas de archivos que hay por sector)
			for( iJ=0 ; iJ <16 ; iJ++) //for( iJ=0 ; iJ < (SECTOR_SIZE / sizeof(stuFsDirectorioFAT)) ; iJ++)
			{

				if( (pstuFsFatDirentAuxFat->filename[0]!=' ') &&(pstuFsFatDirentAuxFat->filename[0]!=FAT_EMPTY) && (pstuFsFatDirentAuxFat->filename[0]!=FAT_DELETED) && !(pstuFsFatDirentAuxFat->attributes & 0x02) && !(pstuFsFatDirentAuxFat->attributes & 0x0D) && !(pstuFsFatDirentAuxFat->attributes & 0x20))
				{
					vFnAdaptarNombre( pstuFsFatDirentAuxFat->filename , stNombreArchivos);

					if ( iFnCompararCadenas( stNombreArchivos, stNombreAux)==1 ) //Devuelve un 1 si la cadena1 es igual a la cadena2
					{
							return pstuFsFatDirentAuxFat->starting_cluster;
					}
				}

				pstuFsFatDirentAuxFat++;
			}

			dwDirSector++;

			if (dwDirSector > (33))//no me tomaba la suma de la funcion por eso tuve q hardcodear
			{
				dwDirSector = LAST_SECTOR;
    			}

		} while (dwDirSector != LAST_SECTOR );

	//Si llegue aqui, archivo no encontrado.
	return -1;
}

/**
 * @brief Busca un directorio en un sector pasado por parametros.
	     Tiene problemas para cuando el directorio q busca no existe.
 * @param PID del proceso
 * @returns Devuelve el cluster de inicio
 * @date 04/08/2008
 */
int iFnBuscar(char *pstNombreAux, int iClusterIni, stuFsHandleFat *pstuFsFatHandleHandle)
{

	char stNombreArchivos[MAX_PATH_LEN];    //String en el que se guarda cada nombre levantado del disco
	char stNombreMay[MAX_PATH_LEN];
	int iJ;
	//Sector de comienzo y cantidad de sectores del directorio a leer
	dword dwDirSector;


	if(iFnCopiaCadena(stNombreMay,pstNombreAux) <= 0)
	{
		vFnImprimir("NO SE COPIO NADA!\n");
		return -1;
	}
	//Pasar el nombre a buscar a mayusculas (recordar que la FAT solo usa mayusculas)
	vFnStrUpr(stNombreMay);
	//El primer directorio a leer sera el Root Dir, asi que cargo sus parametros

	dwDirSector = iClusterIni + 31;
	//uint8_t uRootDirFlag=0;   //Directorio en el que se busca es el Root.

	stuFsDirectorioFAT *pstuFsFatDirentAuxFat;     //Estructura para levantar los datos de cada archivo de disco

	do
	{
		// Leo todo un sector
		if (leerSector(byBuffer ,dwDirSector) ==1)
		{
			vFnImprimir("LEYO\n");
		}

		pstuFsFatDirentAuxFat = (stuFsDirectorioFAT *) byBuffer;

		//Recorro desde 0-16 (que son las cantidad de entradas de archivos que hay por sector)
		for( iJ=0 ; iJ < (16) ; iJ++)
		{

			if( (pstuFsFatDirentAuxFat->filename[0]!=' ') &&(pstuFsFatDirentAuxFat->filename[0]!=FAT_EMPTY) &&
				(pstuFsFatDirentAuxFat->filename[0]!=FAT_DELETED) && !(pstuFsFatDirentAuxFat->attributes & 0x0D) &&
				!(pstuFsFatDirentAuxFat->attributes & 0x20))
			{
				vFnAdaptarNombre( pstuFsFatDirentAuxFat->filename , stNombreArchivos);
				if ( iFnCompararCadenas( stNombreArchivos, stNombreMay)==1 ) //Devuelve un 1 si la cadena1 es igual a la cadena2
				{
					vFnImprimir("EL dwDirSector ES %d\n", pstuFsFatDirentAuxFat->starting_cluster);
					return pstuFsFatDirentAuxFat->starting_cluster;
				}
			}

			pstuFsFatDirentAuxFat++;
		}

		if ((dwDirSector = pstuFsFatHandleHandle->get_next_cluster( pstuFsFatHandleHandle->fat1, dwDirSector ))==53)
		{
			vFnImprimir("el ultimo sector es\n");
			dwDirSector= 53;
			return 0;
		}
	} while (dwDirSector < 53);

	vFnImprimir("no lo encontro\n");
	//Si llegue aqui, archivo no encontrado.
	return 0;
}


/**
 * @brief Usada para verificar la existencia a directorios. Bifurca dependiendo si debe buscar en el root o en otro direcotrio
 * @param Un nombre de directorio del tipo  "CARPETA/"
 * @returns 0 si no encontro u otro numero que se corresponde con el numero de cluster de inicio
 * @date 04/08/2008
 */
int iFnBuscarDirectorio (char *pcNombre, struct stuFsHandleFat * pstuFsFatHandleHandle )
{
	char stNombreAux[255];
	int iDirLen;
	int iClusterIni= 0;
	//barra empieza en 1 ya q cuenta el '/' q tiene al inicio
	//int lon = iFnLongitudCadena(pcNombre);
    
		if ( (iDirLen=iFnBuscarEnCadena(pcNombre,"/",0))>0 )	//devuelve la cantidad hasta la barra
		{	//destino-origen-cant
         iFnCopiaCadena(stNombreAux,pstFnCadenaIzquierda(pcNombre,iDirLen-1));
			iClusterIni=iFnExisteRaiz(stNombreAux,pstuFsFatHandleHandle);

			if( iClusterIni ==-1)//si no se encontro lo seteo con cero
				iClusterIni=0;
		 }
	return iClusterIni;

}

/**
 * @brief Lista el contenido de un directorio en particular
 * @param iClusterIni El numero de cluster a leer
 * @param pstuFsFatHandleHandle la fat
 * @date 04/08/2008
 */
void vFnListarContenidoSubDir(char *stRuta)
{
	//char stNombreArchivos[MAX_PATH_LEN];    //String en el que se guarda cada nombre levantado del disco
	int iJ, iClusterIni;
	dword dwDirSector;
	stuFsDirectorioFAT *pstuFsFatDirentAuxFat;     //Estructura para levantar los datos de cada archivo de disco

   if(iFnCompararCadenas(stRuta, "") ==1)
	{
	  iFnCopiaCadena(stRuta, stuPATHCD[0].stPATH);
	}

		if(iFnCompararCadenas(stRuta, "/") ==1)//LISTA EL DIRECTORIO RAIZ.
		{
			vFnImprimir("listando root dir\n");
			vFnListarRootDir( pstuFsFatHandleHandle);
			return;
		}
		
		if ( stRuta[0] =='/' || stRuta[0] == ' ' )//SI LA RUTA EMPIEZA CON / ESTA MAL
		{
			vFnImprimir("Argumento invalido\n");
			return;
		}
		if(stuPATHCD[0].stPATH[0]=='-' || stuPATHCD[0].stPATH[0]== ""  || stuPATHCD[0].stPATH[0]== " ")
		{vFnImprimir("Argumento invalido\n");return;}
		
		iClusterIni= iFnBuscarDirectorio(stRuta, pstuFsFatHandleHandle);
		if (iClusterIni==0)
		{
			vFnImprimir("Ruta no valida\n");
			return;
		}
		
	 dwDirSector = iClusterIni + 31;

		do
		{
			// Leo todo un sector
		if(leerSector(byBuffer ,dwDirSector)!=1)
		{
		  vFnImprimir("Error al leer sector del diskette");
		  return;
		}
			pstuFsFatDirentAuxFat = (stuFsDirectorioFAT *) byBuffer;

			//Recorro desde 0-16 (que son las cantidad de entradas de archivos que hay por sector)
			for( iJ=0 ; iJ < (16) ; iJ++) //for (iJ = 0; iJ < pstuFsFatHandleHandle->header->root_entries ; iJ++)/
			{

				if((pstuFsFatDirentAuxFat->filename[0]!=' ') && (pstuFsFatDirentAuxFat->filename[0]!=FAT_EMPTY) &&
					iFnCompararCadenas(pstuFsFatDirentAuxFat->filename,"E5")!=1  && !(pstuFsFatDirentAuxFat->attributes & 0x0D) &&
					( (pstuFsFatDirentAuxFat->attributes & 0x20) || (pstuFsFatDirentAuxFat->attributes & 0x10)) )
				{
					iFnListarContenidoDir( pstuFsFatDirentAuxFat );
				}
				pstuFsFatDirentAuxFat++;
			}

			dwDirSector = dwFnObtenerNextClust(dwDirSector);

		} while (dwDirSector < 0xFFF );
	//Si llegue aqui, archivo no encontrado.
//	return ;
}

/**
 * @brief Obtiene el proximo cluster
 * @param dwDirSector Sector de comienzo
 * @date 04/08/2008
 */
dword dwFnObtenerNextClust( dword dwDirSector )
{
	uint16_t uAux;
	uAux =  ( dwDirSector + dwDirSector / 2 );

	if( dwDirSector % 2 )
	{// Entra si es impar
		dwDirSector= (uAux & 0xfff0) * 16;
	}

	else
	{// Entra si es par
		dwDirSector= (uAux & 0x0fff);

	}
        return dwDirSector;
}

/**
 * @brief Setea el proximo cluster
 * @param pstuFsFatHandleHandle La fat
 * @param dwCluster Cluster inicial
 * @param dwNext Proximo cluster
 * @returns El proximo cluster
 * @date 04/08/2008
 */
dword dwFnSetearNextClust(struct stuFsHandleFat * pstuFsFatHandleHandle, dword dwCluster, dword dwNext )
{
	int iN;
	// Obtengo la cantidad de bytes que ocupa la FAT
	//int iFatBytes = 4608;

	//Obtengo la cantidad de sectores que ocupa la FAT
	int iSectores = 9;

	uint16_t *uAux = (uint16_t*)  ( (pstuFsFatHandleHandle->fat1) + (dwCluster) * 3/2 ) ;

	if( dwCluster % 2 )
	{
		*uAux = (dwNext << 4) | (*uAux & 0xf);
	}
	else
	{
		*uAux = dwNext | (*uAux & 0xf000);
	}

	//Este for deberia ser desde el sector(logico) 1 al 9
	for ( iN=1 ; iN<=iSectores ; iN++)
	{
		if( escribirSector(pstuFsFatHandleHandle->fat1 + (512 * iN),iN ) != 1)
			vFnImprimir("No se pudo escribir el sector %d de la iFnObtenerFat12() \n", iN);
	}
	return *uAux;
}

/**
 * @brief Borra un archivo
 * @param pstuFsFatHandleHandle La tabla FAT
 * @param Nombre del archivo
 * @returns 0
 * @date 04/08/2008
 */
int iFnBorrarFat(stuFsHandleFat * pstuFsFatHandleHandle,char * pcNombre)
{
	//XXX Parece incompleto!!!!
	//stuFsDirectorioFAT stuFsFatDirentDatosArchivo;
	dword dwCluster;


	dwCluster = iFnBorrarArcDirectorio(pcNombre);

	return 0;
}

/**
 * @brief Borrado
 * @param pstuFsFatHandleHandle La FAT
 * @param iClusterIni Cluster inicial
 * @date 04/08/2008
 */
void vFnBorrarArcFat (struct stuFsHandleFat * pstuFsFatHandleHandle,int iClusterIni)
{

	dword dwProximoCluster;

	while (iClusterIni < 0xFFF )
	{
		vFnImprimir("iClusterIni %d \n ",iClusterIni);
		dwProximoCluster= dwFnObtenerNextClust( iClusterIni);
		dwFnSetearNextClust(pstuFsFatHandleHandle,iClusterIni, FAT_EMPTY ); // seteo a blanco el sectot con FAT_EMPTY
		iClusterIni = dwProximoCluster;
	}
}

/**
 * @brief Funcion que borra el archivo del root
 * @param pcNombre Nombre del archivo a borrar
 * @returns 0
 * @date 04/08/2008
 */
int iFnBorrarArcDirectorio(char * pcNombre)
{
	char stNombreMay[MAX_PATH_LEN];
	char stNombreArchivos[MAX_PATH_LEN];

	// Obtengo el sector de inicio del directotio root
	int iSectorOriRoot= 19;//sodium_fat_drv_get_root_dir_sector( pstuFsFatHandleHandle->header );//uint16_t iSectorOriRoot
	int iDel = 229;// El numero 229 en hexa es el E5 , que indica que el archivo esta borrado.
	//char cDelH;//Variable en donde se guarda el ascii a colocar en el primer caracter del nombre.
	int iX, iW,iCantSector;
	stuFsDirectorioFAT *pstuFsFatDirentDatos;

	//vFnItoh(iDel, cDelH);//Funcion que convierte el numero 229 en ascii
	// Obtengo la cantidad de sectores totales que ocupa el directorio
	iCantSector = 14;
	iFnCopiaCadena(stNombreMay, pcNombre);
	//Pasar el nombre a buscar a mayusculas (recordar que la FAT solo usa mayusculas)
	vFnStrUpr(stNombreMay);
	//Recorre des el inicio del sector del directorio hasta el numero q abarque la cantidad de sectores que ocupa.
	for ( iX=iSectorOriRoot ; iX < (iSectorOriRoot + iCantSector);iX++) //prueba q funciono
	{
		// Leo todo un sector
		leerSector(byBuffer ,iX);//leerSector(byBuffer ,iSectorOriRoot);
		// Acomodo los bytes de acuerdo al formato de la estructura de directorio
		pstuFsFatDirentDatos = (stuFsDirectorioFAT*)byBuffer;
		// itero hasta la cantidad de entradas por sector (es decir hasta la cantidad de entradas que caben en 512)
		for( iW=0 ; iW < 16 ; iW++)
		{
			// Para cada entrada consulto el primer bit
			//Consulto si el primer valor no es cero, sino es borrado, con 0x0D evito listar los ocultos - del sistema - etiquetas
			//consulto aparte si es oculto por q me los estaba mostrando 0x02
			if ( (pstuFsFatDirentDatos->filename[0]!=FAT_EMPTY) &&
				iFnCompararCadenas(pstuFsFatDirentDatos->filename,"E5")!=1 && //XXX Check for fruta! Esto del E5 como cadena de 2 caracteres 'E' y '5' es medio raro
				!(pstuFsFatDirentDatos->attributes & 0x0D )&&
				!(pstuFsFatDirentDatos->attributes & 0x02)  )
			{
					vFnAdaptarNombre( pstuFsFatDirentDatos->filename , stNombreArchivos);
					if ( iFnCompararCadenas( stNombreArchivos, stNombreMay)==1 )
					{
							// le seteo al nombre el caracter de borrado
							// FIXME MANDAR DE UNA UN 229, pero averiguar si es 229 u otra fruta!
							pstuFsFatDirentDatos->filename[0]= iDel;//cDelH;
							escribirSector(byBuffer, iX);
							return pstuFsFatDirentDatos->starting_cluster;
					}
			}
			pstuFsFatDirentDatos++;
		}
	}
	return 0;
}


/**
 * @brief Levanta las entradas del directorio , y devuelve el puntero al directorio
 * @returns Devuelve el puntero al directorio o NULL sino puede reservar el espacio
 * @date 04/08/2008
 */
uint8_t * t8FnObtenerDirRoot()
{
	// Obtengo la cantidad de sectores del directorio raiz
	uint8_t uCantSectoresRoot  = pstuFsFatHandleHandle->header->root_entries * sizeof(stuFsDirectorioFAT) / SECTOR_SIZE;
	// Obtengo la entrada principal del directorio
	uint8_t uComienzoRoot	= pstuFsFatHandleHandle->header->sectors_per_fat * pstuFsFatHandleHandle->header->fats + 1;
	// Obtengo la cantidad de bytes que ocupa el directorio raiz
	uint8_t uCantBytesRoot    = uCantSectoresRoot * SECTOR_SIZE;
	// Reservo un espacio de la cantidad de bytes que ocupa el directorio
	uint8_t* uBufferRoot = (uint8_t*)pvFnReservarParticionKernel(uCantBytesRoot);

    	if (uBufferRoot == NULL)
    	{
		return NULL;
	}

    	/* read */
	leerSector(uBufferRoot ,uComienzoRoot);


    	return uBufferRoot;
}

/**
 * @brief Lee el primer sector
 * @returns 0 si termino con exito o -1
 * @date 23/10/2008
 */
int iFnObtenerEncabezado()
{
	int iN;
	byte  * byAuxByte;
	word  * wAuxWord;
	dword * dwAuxDword;
	stuSectorBooteo *pstuBootSectorAux;
	if(leerSector(byBuffer, 0) != 1)
	{	vFnImprimir("No se pudo leer sector\n");
		return -1;
	}
 	// casteo el sector leido
  pstuBootSectorAux= (stuSectorBooteo *) byBuffer;
 	/* pido una cantidad de memoria indicada por el tamaño de bloque del dispositivo(512), y la casteo
	a que sea de estructura  stuFsEncabezadoFAT*/
	pstuFsFatHandleHandle->header = (struct stuFsEncabezadoFAT*) pvFnReservarParticionKernel(SECTOR_SIZE);
	/** Lleno mi estructura de header de fat con los valores
		levantados del primer sector
	**/

	for (iN = 0 ; iN < 3 ; iN++)
	{
		byAuxByte = (byte*)(int)byBuffer + iN;
		pstuFsFatHandleHandle->header->ignored[iN] = *byAuxByte ;
	}

	for (iN = 3;iN < 11; iN++) // NO LO IMPRIME BIEN
	{
		byAuxByte = (byte*)(int)byBuffer + iN;
		pstuFsFatHandleHandle->header->oem_id[iN]= *byAuxByte;
	}
	// 512
 	wAuxWord = (word*)(int)byBuffer + 11;
	pstuFsFatHandleHandle->header->bytes_per_sector = *wAuxWord;
	// 1
	byAuxByte = (byte*)(int)byBuffer + 13;
	pstuFsFatHandleHandle->header->sectors_per_cluster = *byAuxByte;
	// 1
	wAuxWord = (word*)(int)byBuffer + 14;
	pstuFsFatHandleHandle->header->reserved_sectors = *wAuxWord;
	// 2
	byAuxByte = (byte*)(int)byBuffer + 16;
	pstuFsFatHandleHandle->header->fats = *byAuxByte;
	// 224
	wAuxWord = (word*)(int)byBuffer + 17;
	pstuFsFatHandleHandle->header->root_entries = *wAuxWord;
	// 2880
	wAuxWord = (word*)(int)byBuffer + 19;
	pstuFsFatHandleHandle->header->small_sectors = *wAuxWord;
	//240
	byAuxByte = (byte*)(int)byBuffer + 21;
	pstuFsFatHandleHandle->header->media_descriptor = *byAuxByte;
	//9
	wAuxWord = (word*)(int)byBuffer + 22;
	pstuFsFatHandleHandle->header->sectors_per_fat = *wAuxWord;
	//12
	wAuxWord = (word*)(int)byBuffer + 24;
	pstuFsFatHandleHandle->header->sectors_per_track = *wAuxWord;
	//2
	wAuxWord = (word*)(int)byBuffer + 26;
	pstuFsFatHandleHandle->header->heads = *wAuxWord;
	//0
	dwAuxDword = (dword*)(int)byBuffer + 28;
	pstuFsFatHandleHandle->header->hidden_sectors = *dwAuxDword;
	//0
	dwAuxDword = (dword*)(int)byBuffer + 32;
	pstuFsFatHandleHandle->header->large_sectors = *dwAuxDword;
	//0
	byAuxByte = (byte*)(int)byBuffer + 36;
	pstuFsFatHandleHandle->header->physical_drive_number = *byAuxByte;
	//0
	byAuxByte = (byte*)(int)byBuffer + 37;
	pstuFsFatHandleHandle->header->current_head = *byAuxByte;
	//41
	byAuxByte = (byte*)(int)byBuffer + 38;
	pstuFsFatHandleHandle->header->signature = *byAuxByte;
	//4294967295
	dwAuxDword = (dword*)(int)byBuffer + 39;
	pstuFsFatHandleHandle->header->volume_id = *dwAuxDword;
	for (iN = 43;iN < 55; iN++)//NO LO IMPRIME BIEN
	{
		byAuxByte = (byte*)(int)byBuffer + iN;
		pstuFsFatHandleHandle->header->volume_label[iN]=*byAuxByte;
	}
	for (iN = 55;iN < 63; iN++)//NO LO IMPRIME BIEN
	{
		byAuxByte = (byte*)(int)byBuffer + iN;
		pstuFsFatHandleHandle->header->fs_type[iN]=*byAuxByte;
	}
	if( !pstuFsFatHandleHandle->header )
	{
		return -1;
	}
	return 0;
}

/**
 * @brief Muestra la cabecera de la FAT
 * @date 23/10/2008
 */
void vFnMostrarEncabezado()
{
	int iN ;
	vFnImprimir("ignored: ") ;
	for (iN = 0 ; iN < 3 ; iN++)
		vFnImprimir("0x%iX",pstuFsFatHandleHandle->header->ignored[iN]) ;

	vFnImprimir("\noem_id: %s\n",pstuFsFatHandleHandle->header->oem_id) ;
	vFnImprimir("bytes_per_sector: %d\n",pstuFsFatHandleHandle->header->bytes_per_sector) ;
	vFnImprimir("sectors_per_cluster: %d\n",pstuFsFatHandleHandle->header->sectors_per_cluster) ;
	vFnImprimir("reserved_sectors: %d\n",pstuFsFatHandleHandle->header->reserved_sectors) ;
	vFnImprimir("fats: %d\n",pstuFsFatHandleHandle->header->fats) ;
	vFnImprimir("root_entries: %d\n",pstuFsFatHandleHandle->header->root_entries) ;
	vFnImprimir("small_sectors: %d\n",pstuFsFatHandleHandle->header->small_sectors );
	vFnImprimir("media_descriptor: %d\n",pstuFsFatHandleHandle->header->media_descriptor) ;
	vFnImprimir("sectors_per_fat: %d\n",pstuFsFatHandleHandle->header->sectors_per_fat) ;
	vFnImprimir("sectors_per_track: %d\n",pstuFsFatHandleHandle->header->sectors_per_track) ;
	vFnImprimir("heads: %d\n",pstuFsFatHandleHandle->header->heads) ;
	vFnImprimir("hidden_sectors: %d\n",pstuFsFatHandleHandle->header->hidden_sectors) ;
	vFnImprimir("large_sectors: %d\n",pstuFsFatHandleHandle->header->large_sectors) ;
	vFnImprimir("physical_drive_number: %d\n",pstuFsFatHandleHandle->header->physical_drive_number );
	vFnImprimir("current_head: %d\n",pstuFsFatHandleHandle->header->current_head) ;
	vFnImprimir("signature: %d\n",pstuFsFatHandleHandle->header->signature);
	vFnImprimir("volume_id: %d\n",pstuFsFatHandleHandle->header->volume_id) ;

	return;
}

/**
 * @brief Leo los sectores de la FAT1
 * @returns 0 si tuvo exito o -1
 * @date 23/10/2008
 */
int iFnObtenerFat12()
{
	int iN;
	// Obtengo la cantidad de bytes que ocupa la FAT
	int iFatBytes = pstuFsFatHandleHandle->header->sectors_per_fat * SECTOR_SIZE;
	//Obtengo la cantidad de sectores que ocupa la FAT
	int iSectores = iFatBytes /SECTOR_SIZE;
	// Reservo una cantidad de memoria de el tamaño de la FAT en bytes
 	pstuFsFatHandleHandle->fat1 = (uint8_t *)pvFnReservarParticionUsuario(iFatBytes);

	//Este for deberia ser desde el sector(logico) 1 al 9
	for ( iN=0 ; iN<iSectores ; iN++)
	{
		if( leerSector(pstuFsFatHandleHandle->fat1 + SECTOR_SIZE * iN,iN ) != 1)
		{
			vFnImprimir("No se pudo leer sector %d de la iFnObtenerFat12() \n", iN);
		}
	}
	for ( iN=0 ; iN<iSectores ; iN++)
	{
		if( leerSector(pstuFsFatHandleHandle->fat3 + SECTOR_SIZE * iN,iN ) != 1)
		{
			vFnImprimir("No se pudo leer sector %d de la iFnObtenerFat12() \n", iN);
		}
	}
	if( !pstuFsFatHandleHandle->fat1 )
		return -1;
	return 0;
}

/**
 * @brief Leo los sectores de la FAT2
 * @returns 0 si tuvo exito o -1
 * @date 04/08/2008
 */
int iFnObtenerCopiaFat12(){
	int iN;
	// Obtengo la cantidad de bytes que ocupa la FAT
	uint8_t fatBytes = pstuFsFatHandleHandle->header->sectors_per_fat * SECTOR_SIZE; // fatBytes era dword pero me trae problemas este tipo
	//Obtengo la cantidad de sectores que ocupa la FAT
	int iSectores = fatBytes /SECTOR_SIZE;
	// Reservo una cantidad de memoria de el tamaño de la FAT en bytes
	pstuFsFatHandleHandle->fat2 = (uint8_t*)pvFnReservarParticionUsuario(fatBytes);

	for ( iN=0 ; iN<iSectores ;iN++)
	{
		if( leerSector(pstuFsFatHandleHandle->fat2 + (SECTOR_SIZE * iN ),iN +(pstuFsFatHandleHandle->header->reserved_sectors + pstuFsFatHandleHandle->header->sectors_per_fat)) != 1)
		{
			vFnImprimir("No se pudo leer sector %d de la iFnObtenerCopiaFat12() \n", iN);
		}
	}

	if( !pstuFsFatHandleHandle->fat2 )
		return -1;

	return 0;
}

/**
 * @brief Prepara el entorno (carga la FAT y el BPB) para que puedan ser utilizadas
	 las demas funciones de acceso a disco
 * @returns 0 si tuvo exito o -1
 * @date 04/08/2008
 */
int iFnIniciarFileSystFloppy()
{
	if(iFnObtenerEncabezado()!=0)
		return -1;

	if(iFnObtenerFat12()!=0)
		return -1;

	if(iFnObtenerCopiaFat12()!=0)
		return -1;

	iFnCargarFAT();

   return 0;
}

/**
 * @brief Obtiene del diskett el boot sector y el puntero a la fat
 * @returns 0 si se ejecut� correctamente, si tuvo error devuelve -1 o -2
 * @date 04/08/2008
 */
int iFnIniciarFatDrv ()
 {

  //Header de una lista enlazada que va apuntando a bloques en memoria de 512
  //(fragmentos de la FAT)
 /* inicialización primaria: */
	pstuFsFatHandleHandle->header = NULL;
	pstuFsFatHandleHandle->fat1 = NULL;
	pstuFsFatHandleHandle->fat2 = NULL;

	pstuFsFatHandleHandle->get_constant = NULL;
	pstuFsFatHandleHandle->get_next_cluster = NULL;
	pstuFsFatHandleHandle->set_next_cluster = NULL;

	if(iFnIniciarFileSystFloppy() != 0)
	{
		vFnImprimir( "\nNO SE PUDO INICIALIZAR EL FLOPPY\n" );
		return -1;
	}

	 if( !memcmp( pstuFsFatHandleHandle->fat1, FAT12_HEADER, FAT12_HEADER_SIZE ) )
	{
		pstuFsFatHandleHandle->get_constant = t16FnFat12DrvGetConst;
		pstuFsFatHandleHandle->get_next_cluster = t16FnFat12DrvGetNextClust;
		pstuFsFatHandleHandle->set_next_cluster = t16FnFat12DrvSetNextClust;
	}
	else if( !memcmp( pstuFsFatHandleHandle->fat1, FAT12B_HEADER, FAT12_HEADER_SIZE ) )
	{
		pstuFsFatHandleHandle->get_constant = t16FnFat12DrvGetConst;
		pstuFsFatHandleHandle->get_next_cluster = t16FnFat12DrvGetNextClust;
		pstuFsFatHandleHandle->set_next_cluster = t16FnFat12DrvSetNextClust;
	}
	else
	{
		return -2;
	}
	return 0;
 }


/**
 * @brief Devuelve el estado del cluster
 * @date 04/08/2008
 */
void vFnIniciarCacheFloppy ()
{
	int iN;

	for(iN=0 ; iN< 511 ; iN++)
	{
		byBufferRead[iN]=0;
    	}

   return;
}

/**
 * @brief Lee archivo
 * @param dwSector Sector a leer
 * @date 04/08/2008
 */
void vFnLeerArchivo (dword dwSector)
{
	int iN;

	if(leerSector(byBufferRead, dwSector+31) != 1)
	{
		vFnImprimir("No se pudo leer sector %d\n", dwSector);
		return;
	}

	for ( iN=0;  iN<512  ;  iN++ )
		vFnImprimir("%c", byBufferRead[iN]);

}

/**
 * @brief Devuelve el estado del cluster
 * @param uConstante Cluster a verificar estado
 * @returns 0 si el cluster se encuentra ok.
 * @date 04/08/2008
 */
uint16_t t16FnFat12DrvGetConst( uint16_t uConstante ){
	switch( uConstante )
	{
		case( FAT_FREE_CLUSTER ): return FAT12_FREE_CLUSTER;
		case( FAT_RESERVED_CLUSTER ): return FAT12_RESERVED_CLUSTER;
		case( FAT_USED_CLUSTER ): return FAT12_USED_CLUSTER;
		case( FAT_BAD_CLUSTER ): return FAT12_BAD_CLUSTER;
		case( FAT_LAST_CLUSTER ): return FAT12_LAST_CLUSTER;
		default: return 0;
	}
}

/**
 * @brief Muestar el contenido del archivo de la unidad
 * @param pcNombre nombre del archivo a mostrar
 * @date 04/08/2008
 */
void vFnDispLeerArchivo(char *pcNombre)
{
	stuFsDirectorioFAT stuFsFatDirentDatosArchivo;
	stuFsDirectorioFAT *pstuFsFatDirentDatosArchivo=&stuFsFatDirentDatosArchivo;
	uint32_t uCluster;
	uint32_t uTamanioArchivo;
	int iCantSectores, iSectoresLeidos=0;
	//provisorio hasta crear un comando mount para cargar el pstuFsFatHandleHandle
	iFnObtenerEncabezado();
	iFnCargarFAT();
	vFnCargarRootDir();
	if(iFnBuscarArchivoFat (pcNombre, pstuFsFatDirentDatosArchivo, pstuFsFatHandleHandle) == 1)
	{
		vFnImprimir("Nombre: %s\n", pstuFsFatDirentDatosArchivo->filename) ;
		vFnImprimir("Cluster Inicial: %d\n", pstuFsFatDirentDatosArchivo->starting_cluster);
		uCluster = pstuFsFatDirentDatosArchivo->starting_cluster;
		uTamanioArchivo = pstuFsFatDirentDatosArchivo->filesize;

		iCantSectores = (uTamanioArchivo/512);
		if((uTamanioArchivo % 512) !=0)
		{
			iCantSectores = iCantSectores +1;
		}
		vFnImprimir("Cantidad de Sectores a leer: %d\n", iCantSectores);
		vFnImprimir("\nCONTENIDO DEL ARCHIVO:\n");
		while((iSectoresLeidos < iCantSectores))
		{
			vFnLeerArchivo(uCluster);
			uCluster = uiFnBuscarNextSector(uCluster);
			iSectoresLeidos++;
		}
	}
	else
	{
		vFnImprimir("\nArchivo %s no encontrado\n", pcNombre);
		return;
	}

	return;
}

/**
 * @brief Compara si el contenido de la memoria es el mismo solo la cantidad determinada de bytes
 * @param pconvS1 Cadena a comparar
 * @param pconvS2 Cadena a comparar
 * @param dwN Cantidad de bytes
 * @returns La diferencia en los bytes con error o 0 si no existe diferencia
 * @date 04/08/2008
 */
int memcmp(const void *pconvS1, const void *pconvS2, dword dwN)
{
	byte *bySS2 = (byte *) pconvS2;
     	byte *byS11 = (byte *) pconvS1;

     	while (dwN--)
	{
         	if (*byS11 != *bySS2 )
             		return (int) (byS11-bySS2);
         	bySS2++;byS11++;
     	}

     	return 0;
}

/**
 * @brief Devuelve el sector q le sigue
 * @param uFat Numero de posicion de la FAT
 * @param uCluster Numero de cluster en el que estamos
 * @returns El proximo cluster
 * @date 04/08/2008
 */
uint16_t t16FnFat12DrvGetNextClust( uint8_t *uFat, uint16_t uCluster )
{
	uint16_t uAux =  ( uCluster + uCluster / 2 );
	if( uCluster % 2 )
	{// Entra si es impar
		return (uAux & 0xfff0) * 16;
	}
	else
	{// Entra si es par
		return (uAux & 0x0fff);
	}
}

/**
 * @brief Setea el proximo sector.
 * @param uFat Numero de posicion de la FAT
 * @param uCluster Numero de cluster en el que estamos
 * @param dwNext Proximo cluster para setear
 * @returns El proximo cluster seteado
 * @date 04/08/2008
 */
uint16_t t16FnFat12DrvSetNextClust( uint8_t *uFat,uint16_t uCluster, uint16_t dwNext )
{
	uint16_t *uAux = (uint16_t*) t8FnFatDrvGetClustAddr( uFat, uCluster );

	if( uCluster % 2 ){
		*uAux = (dwNext << 4) | (*uAux & 0xf);
	}
	else
	{
		*uAux = dwNext | (*uAux & 0xf000);
	}

	return *uAux;
}

/**
 * @brief Devuelve el offset del sector buscado, dentro de la FAT
 * @param uFat Valor a buscar
 * @param uCluster Cluster a buscar
 * @returns El offset del sector buscado, dentro de la FAT
 * @date 04/08/2008
 */
uint8_t* t8FnFatDrvGetClustAddr( uint8_t *uFat, uint16_t uCluster )
{
	return( (uFat) + (uCluster) * 3/2 );
}


/**
 * @brief Escribe en el Dispositivo
 * @param pcNombre Nombre del archivo
 * @param pcContArch Tamanio del archivo
 * @date 04/08/2008
 */
int iFnDispEscribirArchivo (char *pcNombre, char *pcContArch){

    int iIndiceFat, iIndiceRootDir;
    struct stuFsDirectorioFAT stuFsFatDirentEntrada;

	  iFnCargarFAT();
	  vFnCargarRootDir();

    iIndiceFat = iFnBuscarEntradaFATLibre();
    vFnImprimir("\nCopiando en FAT: %d", iIndiceFat);

    iIndiceRootDir = iFnBuscarEntradaFATVacia();
    vFnImprimir("\tRoot Directory: %d", iIndiceRootDir);

    if(iIndiceFat==-1 || iIndiceRootDir==-1){
        return -1;
    }
    vFnConvierteNombreToFAT(pcNombre,stuFsFatDirentEntrada.filename);
    stuFsFatDirentEntrada.attributes=0x20;//le decimos que es un archivo
    stuFsFatDirentEntrada.reserved=0;
    stuFsFatDirentEntrada.create_time=0;
    stuFsFatDirentEntrada.create_date=0;
    stuFsFatDirentEntrada.access_date=0;
    stuFsFatDirentEntrada.ea_index=0;
    stuFsFatDirentEntrada.modified_time=0;
    stuFsFatDirentEntrada.modified_date=0;
    stuFsFatDirentEntrada.starting_cluster=iIndiceFat;
    stuFsFatDirentEntrada.filesize=iFnObtenerTamanioArchivo(pcContArch);

    stuFsDirectorioFATRootDir[iIndiceRootDir]=stuFsFatDirentEntrada;
    // hacer un set entrada fat y le pongo que ahi termina el archivo (0xFFF)

    vFnSetearEnFat(iIndiceFat,0xFFF);

    vFnRootDirToFloppy();
    vFnCopiaFatToFloppy();

    //Iniciando carga del contenido
    int iN, cant=0, caracteres=0;
    while(pcContArch[cant]!='\0')
	{
	 stCadenaAux[cant]=pcContArch[cant];
	 caracteres++;
         cant++;
	}
    for (iN = caracteres; iN < 512; iN++)
		stCadenaAux[iN]=' ';

    ucpFnCopiarMemoria((unsigned char*)byBufferRead, (unsigned char*)stCadenaAux, 512);
    escribirSector(byBufferRead, (((iIndiceFat-2)*1)+33));
    return 0;
}

///////////////////////////////////
/**
 * @brief Calcula el tama�o de un archivo
 * @param pcContArch Contador del archivo
 * @returns Tama�o del archivo
 * @date 04/08/2008
 */
int iFnObtenerTamanioArchivo(char * pcContArch)
{
    	int iCantCaracteres=0;
	
	iFnCopiaCadena(stArgAux, pcContArch);

	while(stArgAux[iCantCaracteres]!='\0')
	{
	 	iCantCaracteres++;
	}

	iCantCaracteres++;

	if (iCantCaracteres < 128)
		return (iCantCaracteres);
	else
		return 512;
}

////////////////////////////////////
/**
 * @brief Busca una entrada libre
 * @returns La entrada libre si exite o -1 si no existe
 * @date 04/08/2008
 */
int iFnBuscarEntradaFATLibre(){
   int iN=0;
    for (iN=35;iN<=2848;iN++){
        if(uiFnBuscarNextSector(iN) == 0x00){
	        return iN;
        }
    }
    return -1;
}
////////////////////////////////////
/**
 * @brief Busca una entrada Vaciaen la FAT
 * @returns La entrada vac�a si exite o -1 si no existe
 * @date 04/08/2008
 */
int iFnBuscarEntradaFATVacia(){
    int iN=0;
    for (iN=0;iN<224;iN++){
        if(stuFsDirectorioFATRootDir[iN].filename[0] == 0x00 || stuFsDirectorioFATRootDir[iN].filename[0] == 0xE5){
			return iN;        
		}
    }
    return -1;
}
////////////////////////////////////
/**
 * @brief Copia el directorio del Root al diskette
 * @date 04/08/2008
 */
void vFnRootDirToFloppy(){
	int iN,iJ, iDesplazamiento=0;
	unsigned char * pRootDir=(unsigned char *)stuFsDirectorioFATRootDir;
	//son 14 sectores a partir del 19
	for(iN=0;iN<14;iN++){
                for(iJ=0;iJ<512;iJ++){
                    byBuffer[iJ] = pRootDir[iJ+iDesplazamiento];
                }
                escribirSector(byBuffer,iN+19);
                iDesplazamiento += 512;
        }
}
////////////////////////////////////
/**
 * @brief Copia la Fat al disco
 * @date 04/08/2008
 */
void vFnCopiaFatToFloppy(){
	int iN;
	char * pFat = pTablaFat1;
	// actualizar fat1
	for(iN=1;iN<=9;iN++){						//CAMBIADO
    ucpFnCopiarMemoria((unsigned char*)byBuffer, (unsigned char*)pFat, 512 );				//CAMBIADO
		escribirSector(byBuffer,iN);
		pFat+=512;
        }
	// actualizar fat2 (copiamos la fat1 en donde va la 2)
	pFat=pTablaFat1;
	for(iN=1+9;iN<=9*2;iN++){					//CAMBIADO
		ucpFnCopiarMemoria( (unsigned char*)byBuffer, (unsigned char*)pFat, 512 );			//CAMBIADO
		escribirSector(byBuffer,iN);
		pFat+=512;
        }
}
////////////////////////////////////
/**
 * @brief Carga en memoria el stuFsDirectorioFATRootDir
 * @date 04/08/2008
 */
void vFnCargarRootDir(){
	int iN,iJ=0,iK=0,iU,iIni=0,iFin=16,iOffset=0,iY;
	// Ubicamos en que sector empieza el directorio raiz
	//unsigned int uiRootDir=pstuFsFatHandleHandle->header->reserved_sectors+(pstuFsFatHandleHandle->header->sectors_per_fat*pstuFsFatHandleHandle->header->fats);
	// Vemos cuantos sectores ocupa el directorio raiz
        //unsigned int root_dir_sectors = 14;
        //Tamanio de cantidad de sectores * 512
        stuFsDirectorioFATRootDir = pvFnReservarParticionUsuario(224*32);
        // Leemos tantos sectores a partir del 19 como sectores tenga el rootdir.
        // con este primer for vamos leyendo c/u de los sectores
        for(iN=1;iN<=14;iN++){ //son 14 sectores de stuFsDirectorioFATRootDir.
                leerSector(byBuffer,iN+18);
		for(iY=iIni;iY<iFin;iY++){
                   if(iY>224){break;}
                   if((int)byBuffer[11+iOffset] != 15){
                      for(iU=0;iU<11;iU++){
                         stuFsDirectorioFATRootDir[iJ].filename[iU]=byBuffer[iK+iOffset];
                         iK++;
                      }
                      stuFsDirectorioFATRootDir[iJ].attributes = byBuffer[11+iOffset];
		              stuFsDirectorioFATRootDir[iJ].reserved=(short)byBuffer[12+iOffset];
                      stuFsDirectorioFATRootDir[iJ].reserved|=(short)byBuffer[13+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].create_time=(short)byBuffer[14+iOffset];
                      stuFsDirectorioFATRootDir[iJ].create_time|=(short)byBuffer[15+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].create_date=(short)byBuffer[16+iOffset];
                      stuFsDirectorioFATRootDir[iJ].create_date|=(short)byBuffer[17+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].access_date=(short)byBuffer[18+iOffset];
                      stuFsDirectorioFATRootDir[iJ].access_date|=(short)byBuffer[19+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].ea_index=(short)byBuffer[20+iOffset];
                      stuFsDirectorioFATRootDir[iJ].ea_index|=(short)byBuffer[21+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].modified_time=(short)byBuffer[22+iOffset];
                      stuFsDirectorioFATRootDir[iJ].modified_time|=(short)byBuffer[23+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].modified_date=(short)byBuffer[24+iOffset];
                      stuFsDirectorioFATRootDir[iJ].modified_date|=(short)byBuffer[25+iOffset]<<8;
                      stuFsDirectorioFATRootDir[iJ].starting_cluster = (short)byBuffer[26+iOffset];
                      stuFsDirectorioFATRootDir[iJ].starting_cluster |= (short)byBuffer[27+iOffset] << 8;
                      stuFsDirectorioFATRootDir[iJ].filesize = (short)byBuffer[28+iOffset];
                      stuFsDirectorioFATRootDir[iJ].filesize |= (short)byBuffer[29+iOffset] << 8;
                      stuFsDirectorioFATRootDir[iJ].filesize |= (short)byBuffer[30+iOffset] << 16;
                      stuFsDirectorioFATRootDir[iJ].filesize |= (short)byBuffer[31+iOffset] << 24;
                     iJ++;
                     iK=0;
                   }
                   iOffset += 32;
                }
            iIni+=16;
            iFin+=16;
            iOffset=0;
        }
}

////////////////////////////////////
/**
 * @brief Carga las Fat en memoria
 * @returns 0 si puede cargarlas o -1 si no puede realizarlo
 * @date 04/08/2008
 */
int iFnCargarFAT()
{	//XXX El tamaño del buffer debe depender del tipo de fat y el tamaño del medio
	unsigned short usTamnioFat=10*512;
	int iN,iJ;

	pTablaFat1 = pvFnReservarParticionUsuario(usTamnioFat);
	pTablaFat2 = pvFnReservarParticionUsuario(usTamnioFat);

	if(!pTablaFat1 || !pTablaFat2){
		vFnImprimir("Sin memoria para levantar la FAT\n");
		return -1;
        }

  for(iN=1+9;iN<=18;iN++){
		leerSector(byBuffer,iN);
    for(iJ=0;iJ<512;iJ++){
		  pTablaFat2[iJ+((iN-(1+9))*512)]=byBuffer[iJ];
    }
  }

	for(iN=1;iN<=9;iN++){
		leerSector(byBuffer,iN);
		for(iJ=0;iJ<512;iJ++){
			pTablaFat1[iJ+((iN-1)*512)]=byBuffer[iJ];
    }
  }
	return 0;
}
////////////////////////////////////
/**
 * @brief Busca el proximo sector
 * @param uiSector en el cual estoy parado
 * @returns El proximo sector
 * @date 04/08/2008
 */
unsigned int uiFnBuscarNextSector(unsigned int uiSector){
   return usFnObtenerSectorFat(uiSector);
}
////////////////////////////////////
/**
 * @brief Seteo el sector en la fat
 * @param usSector Sector con el cual estoy trabajando
 * @param usValor Valor a setear
 * @date 04/08/2008
 */
void vFnSetearEnFat(unsigned short usSector,unsigned short usValor){

        unsigned char ucAux = 0;
        unsigned char ucAux2 = 0;

        if(usSector%2==0){
           //PRIMER PARTE
           // separo lo que necesito dejar igual
           ucAux=(unsigned char)pTablaFat1[((6*usSector)/4)+1] & 0xF0;
           // separo del vaor de entrada los 4 bits mas altos
           ucAux2=(unsigned char) usValor>>8;
           ucAux|=ucAux2;
           pTablaFat1[((6*usSector)/4)+1]=ucAux;
    		//SEGUNDA PARTE
			// separo del vaor de entrada los 8 bits mas bajos
		   ucAux=(unsigned char) usValor && 0x00FF;
		   pTablaFat1[(6*usSector)/4]=ucAux;
        }
    	else{
           ucAux=(unsigned char)pTablaFat1[(6*usSector)/4] & 0x00F0;
           //separo los 4bits mas bajos de la entrada
		       ucAux2=(unsigned char) usValor && 0x000F;
		       ucAux|=ucAux2;
		       //separo los 8bits mas altos
		       ucAux=(unsigned char)usValor>>4;
		       pTablaFat1[((6*usSector)/4)+1]=ucAux;
        }
}
////////////////////////////////////
/**
 * @brief Devuelve la posicion de la fat a partir de un sector dado
 * @param usSector sector a buscar
 * @returns Posici�n de la FAT
 * @date 04/08/2008
 */
unsigned short usFnObtenerSectorFat(unsigned short usSector){

        unsigned short usAux = 0;

        if(usSector%2==0){
           usAux=(unsigned short)pTablaFat1[((6*usSector)/4)+1] & 0x000F;
           usAux=usAux<<8;
           usAux|=(unsigned short)pTablaFat1[(6*usSector)/4];
        }
        else{
           usAux=(unsigned short)pTablaFat1[(6*usSector)/4] & 0x00F0;
           usAux=usAux>>4;
           usAux|=((unsigned short)pTablaFat1[((6*usSector)/4)+1])<<4;
        }
        return (unsigned short) usAux;
}

////////////////////////////////////
/**
 * @brief Convierte la cadena a may�scula
 * @param stCadena Cadena a convertir
 * @returns Cadena convertida
 * @date 04/08/2008
 */
 // se usa funcion en libk
/*
char* pcPasarAMayuscula(char* stCadena){
     char* pcStrRet = stCadena;
     int iN;
     for(iN=0;iN<iFnLongitudCadena(stCadena);iN++){
         if((stCadena[iN] >= 'a') && (stCadena[iN]<= 'z')){
             stCadena[iN] -= 32;
         }
     }
     return pcStrRet;
}*/
////////////////////////////////////
/**
 * @brief Convierte una cadena a algo entendible por la FAT
 * @param pcNombre Nombre a convertir
 * @param pucNombreAdaptado Nombre convertido
 * @date 04/08/2008
 */
void vFnConvierteNombreToFAT(char *pcNombre, char *pucNombreAdaptado){
     int iZ,iPunto=0,iX=0;
     vFnStrUpr(pcNombre);
     for(iZ=0;iZ<11;iZ++){
        if(pcNombre[iX]=='.'){
            iPunto=1;
            iX++;
        }
        if((iZ<8 && iPunto==1) || pcNombre[iX]=='\0'){
            pucNombreAdaptado[iZ]=' ';
        }
        else{
            pucNombreAdaptado[iZ]=pcNombre[iX];
            iX++;
        }
     }
}
////////////////////////////////////
////////////////////////////////////
//FUNCIONES DE TESTING
void imprimirTablaFAT( char *pcFat )
{
	byte byLsb, byMsb;//, byB;
	word wSector=1, wSigSector;
	//char stC[3];
	int iN;
	byte *pbyP=(byte*)pcFat;

	vFnImprimir( "\nImprimiendo Tabla FAT \n");
	for( iN=0; iN<(512*9); iN++ );
	{
		vFnImprimir( "%xb", *pbyP++ );
		if ((iN%3)==0)
			vFnImprimir( "\t" );
	}
	vFnImprimir( "\nFAT ha sido impresa\n" );
//	cFnGetChar();

	pbyP = (byte *)pcFat;
	for( iN=0; iN<(512*9); iN+=2 );
	{
		byLsb = *pbyP++;
		byMsb = *pbyP++;

		if( wSector % 2)
			wSigSector = (((byMsb << 8 ) | byLsb)& 0xfff0 ) >> 4;
		else
			wSigSector = (( byMsb << 8 ) | byLsb) & 0x0fff ;
		wSector++;
		vFnImprimir( ":%d\t", wSigSector );
	}
	cFnGetChar();

}
////////////////////////////////////
int TEST_WRITE_READ()
{
    vFnImprimir("Inicio TEST_WRITE_READ()");
    SHELL_INTERACTIVO;
    byte byAux;
    int iN;
    byAux = 0xab;
    for (iN = 0; iN < 512; iN++)
	byBufferRead[iN] = byAux;
    escribirSector(byBufferRead, 1000);
    leerSector(byBuffer,1000);
    for (iN = 0; iN < 512; iN++)
	vFnImprimir("%iX",byBuffer[iN]);
	return 1;
}
////////////////////////////////////
void TEST_BUSCA_FAT()
{
	int iN=0,iJ=0;
	for (iN=35;iN<=2848;iN++){
		if(uiFnBuscarNextSector(iN) == 0x00){
		iJ++;
		}
	}

	vFnImprimir("Entradas Vacias: %d",iJ);
}
